package StructuralPattern.Proxy.DynamicProxy;


import java.lang.reflect.Proxy;

/**
 * @Classname : ProxyClient
 * @Description : 测试 代理设计模式（动态代理/JDK代理/接口代理）
 * 动态代理：
 *   1、使用建议：优先使用动态代理，通过反射实现，无需单独创建一个实现对应接口的代理类，便于维护
 *   2、静态代理在编译完成后代理类是一个实际的 class 文件，动态代理是在运行时动态生成的，即编译完成后没有实际的 class 文件，而是在运行时动态生成类字节码，并加载到 JVM 中
 *   3、动态代理要求目标对象必须实现接口
 *
 * 行为型——代理模式
 * 一、模式定义
 *   Provide a surrogate or placeholder for another object to control access to it.
 *   为其他对象提供一种代理来控制对这个对象的访问。
 * 二、模式类图
 *   https://kdocs.cn/l/ciONa1Oke0pR
 * 三、适用场景
 *   1、引入代理间接访问目标对象，防止直接访问目标对象对系统带来的风险。
 *   2、代理角色主要用于对具体角色进行功能扩展（方法执行前后补充一些通用的重复的操作）。
 * 四、应用举例
 *   1、数据库连接池关闭处理
 *   2、mybatis中实现拦截器插件
 *   3、AspectJ的实现
 *   4、spring中AOP的实现（日志拦截、声明式事务处理）
 *   5、RMI远程方法调用
 *
 * @Author : chentianyu
 * @Date 2023/2/11 22:59
 */


public class ProxyClient {
    public static void main(String[] args) {

        System.out.println("具体角色执行操作");
        GamePlayer zhangsan = new ConcreteGamePlayer("zhangsan");
        zhangsan.login();
        zhangsan.killBoss();
        zhangsan.upgrade();
        System.out.println("--------------------------------------------------------------------");

        System.out.println("代理角色执行操作");
        GamePlayer proxy = (GamePlayer) Proxy.newProxyInstance(
                zhangsan.getClass().getClassLoader(),  // 或 ClassLoader.getSystemClassLoader()
                new Class[]{GamePlayer.class},
                new GamePlayerHandler(zhangsan)
        );
        proxy.login();
        proxy.killBoss();
        proxy.upgrade();
        System.out.println("--------------------------------------------------------------------");
    }
}

/** 20230212
 * 具体角色执行操作
 * 玩家 zhangsan 登录成功！
 * 玩家 zhangsan 在打怪！
 * 玩家 zhangsan 又升了一级！
 * --------------------------------------------------------------------
 * 代理角色执行操作
 * 玩家 zhangsan 登录成功！
 * 玩家 zhangsan 在打怪！
 * 玩家 zhangsan 又升了一级！
 * 每升一级计费100元。
 * --------------------------------------------------------------------
 */
